package com.hbx.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.hbx.auth.AuthCacheService;
import com.hbx.auth.jwt.JwtUser;
import com.hbx.auth.jwt.JwtUtil;
import com.hbx.constant.*;
import com.hbx.dto.AdminLoginDto;
import com.hbx.dto.user.CheckPwdDto;
import com.hbx.dto.user.UpdatePwdDto;
import com.hbx.dto.user.UpdateUserDto;
import com.hbx.dto.user.UserAuthDto;
import com.hbx.dto.user.UserInsertDto;
import com.hbx.dto.user.UserRankDto;
import com.hbx.dto.user.UserRegisterDto;
import com.hbx.dto.user.UserSearchDto;
import com.hbx.exception.RspException;
import com.hbx.logs.annotation.MarkLog;
import com.hbx.logs.OperaTypeEnum;
import com.hbx.mapper.RoleUserMapper;
import com.hbx.mapper.UserRankMapper;
import com.hbx.model.Occupation;
import com.hbx.model.Rank;
import com.hbx.model.RoleUser;
import com.hbx.model.User;
import com.hbx.mapper.UserMapper;
import com.hbx.model.UserRank;
import com.hbx.service.MenuService;
import com.hbx.service.OccupationService;
import com.hbx.service.RankService;
import com.hbx.service.UserService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hbx.utils.CacheUtils;
import com.hbx.utils.FileUploadUtil;
import com.hbx.utils.MailSendUtil;
import com.hbx.utils.Result;
import com.hbx.utils.StringUtil;
import com.hbx.vo.RankVo;
import com.hbx.vo.UserInfoVo;
import com.hbx.vo.login.AuthResultVo;
import com.hbx.vo.login.MenuVo;
import com.hbx.vo.SearchUserVo;
import lombok.extern.slf4j.Slf4j;
import org.jasypt.util.password.PasswordEncryptor;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.mail.MessagingException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.StringJoiner;
import java.util.UUID;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author hbx
 * @since 2021-11-26
 */
@Service
@Slf4j
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    @Value("${auth.expires:1800000}")
    public Long expires;

    @Value("${auth.scriect:1174586985@22.com}")
    public String scricet;

    @Autowired
    private PasswordEncryptor passwordEncryptor;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private MailSendUtil mailSendUtil;

    @Autowired
    private MenuService menuService;

    @Autowired
    private CacheUtils cacheUtils;

    @Autowired
    private RankService rankService;

    @Autowired
    private OccupationService occupationService;

    @Autowired
    private FileUploadUtil fileUploadUtil;

    @Autowired
    private RoleUserMapper roleUserMapper;

    @Autowired
    private UserRankMapper userRankMapper;

    /**
     * 检查用户名是否存在
     *
     * @param username
     * @return
     */
    @Override
    public Result<Integer> checkUsernameExist(String username) {
        // 构造条件
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("login_name", username);
        List<User> userList = userMapper.selectList(queryWrapper);
        if (!ObjectUtils.isEmpty(userList) && userList.size() > 0) {
            // 说明用户名已存在
            log.warn("【用户模块】:用户名:{}已存在,检验不通过", username);
            return Result.ok().setData(userList.size());
        }
        //  不存在
        log.info("【用户模块】:用户名:{}检验通过", username);
        return Result.ok().setData(0);
    }

    /**
     * 用户注册
     *
     * @param user
     * @return
     */
    @Override
    @MarkLog(operate = OperaTypeEnum.INSERT,tables = {TableEnum.SYS_USER},desc = "用户注册")
    public Result register(UserRegisterDto user) {
        // 判断用户是否存在
        Result<Integer> r = checkUsernameExist(user.getUsername());
        if (r.getData() > 0) {
            // 用户已存在
            return Result.ok("用户:" + user.getUsername() + "已存在").setCode(201);
        }
        // 生成盐
        String salt = StringUtil.generatorUniqueSalt();
        String password = passwordEncryptor.encryptPassword(user.getPassword());
        User userEntity = new User();
        userEntity.setSalt(salt);
        userEntity.setLoginName(user.getUsername());
        userEntity.setPwd(password);
        userEntity.setRegisterTime(new Date());
        userEntity.setEmail(user.getEmail());

        int insert = userMapper.insert(userEntity);
        if (insert == 1) {
            try {
                // 授权
                RoleUser roleUser = new RoleUser();
                roleUser.setUid(userEntity.getUserId());
                roleUser.setRid(3);
                if (roleUserMapper.insert(roleUser) != 1){
                    return Result.error("用户:" + user.getUsername() + "注册失败,请重新尝试");
                }
                // 授衔
                UserRank rank = new UserRank();
                rank.setUserId(userEntity.getUserId());
                rank.setRankId(2);
                if (userRankMapper.insert(rank) != 1){
                    return Result.error("用户:" + user.getUsername() + "注册失败,请重新尝试");
                }
                // 发送邮件激活,注册成功
                log.info("【用户模块】:用户:{}注册成功", user.getUsername());
                String content = "恭喜用户:" + user.getUsername() + "注册成功,请在3天内激活用户,激活码为:" + salt;
                mailSendUtil.send("资源共享平台",new String[]{user.getEmail()}, content);
                return Result.ok("用户:" + user.getUsername() + "注册成功,请查看邮箱激活");
            } catch (Exception e) {
                throw new RspException(ResponseStateConstant.SERVER_ERROR, "服务器异常,请稍后再试");
            }
        }
        log.error("【用户模块】:用户:{}注册失败", user.getUsername());
        throw new RspException(ResponseStateConstant.OPERA_FAIL, "注册失败");
    }

    /**
     * 激活用户
     *
     * @param code
     * @return
     */
    @Override
    @Transactional
    @MarkLog(operate = OperaTypeEnum.UPDATE,tables = {TableEnum.SYS_USER},desc = "激活用户")
    public Result activeUser(String code) {
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.eq("salt",code);
        List<User> userList = userMapper.selectList(wrapper);
        if (CollectionUtils.isEmpty(userList)){
            return Result.error().setMsg("激活码有误,请核对后重试");
        }
        User currentUser = userList.get(0);
        if (currentUser != null && currentUser.getAvailable() == 1){
            return Result.ok().setCode(2008).setMsg("用户已经激活,请勿重复操作");
        }
        User user = new User();
        user.setAvailable(1);
        UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("salt", code);

        int update = userMapper.update(user, updateWrapper);
        if (update == 1) {
            log.info("【用户模块】:用户激活成功");
            return Result.ok("激活成功");
        }
        log.error("【用户模块】:用户激活失败");
        throw new RspException(ResponseStateConstant.OPERA_FAIL, "用户激活失败");
    }

    /**
     * 条件查询用户
     *
     * @param userSearch
     * @return
     */
    @Override
    public Result<SearchUserVo> pageListByQuery(UserSearchDto userSearch) {

        Page<User> page = new Page<>(userSearch.getPageNum(), userSearch.getPageSize());
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.orderByAsc("type");
        // 封装查询条件
        if (StringUtils.hasLength(userSearch.getAddress())) {
            wrapper.like("address", userSearch.getAddress());
        }
        if (!ObjectUtils.isEmpty(userSearch.getAvailable()) && userSearch.getAvailable() != 0) {
            wrapper.eq("available", userSearch.getAvailable());
        }

        if (StringUtils.hasLength(userSearch.getEmail())) {
            wrapper.like("email", userSearch.getEmail());
        }

        if (StringUtils.hasLength(userSearch.getIdentity())) {
            wrapper.like("identity", userSearch.getIdentity());
        }

        if (StringUtils.hasLength(userSearch.getKeyword())) {
            String keyword = userSearch.getKeyword();
            wrapper.like("address", keyword).or()
                    .like("login_name", keyword).or()
                    .like("identity", keyword).or()
                    .like("email", keyword).or()
                    .like("available", keyword).or()
                    .like("real_name", keyword).or()
                    .like("sex", keyword).or()
                    .like("phone", keyword).or()
                    .like("type", keyword);
        }

        if (!ObjectUtils.isEmpty(userSearch.getLastLoginTime())) {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            String date = sdf.format(userSearch.getLastLoginTime());
            wrapper.apply("date_format(last_login_time, '%Y-%m-%d') = {0}", date);
        }

        if (StringUtils.hasLength(userSearch.getLoginName())) {
            wrapper.like("login_name", userSearch.getLoginName());
        }
        if (StringUtils.hasLength(userSearch.getPhone())) {
            wrapper.like("phone", userSearch.getPhone());
        }

        if (StringUtils.hasLength(userSearch.getRealName())) {
            wrapper.like("real_name", userSearch.getRealName());
        }

        if (!ObjectUtils.isEmpty(userSearch.getSex())) {
            wrapper.eq("sex", userSearch.getSex());
        }

        if (!ObjectUtils.isEmpty(userSearch.getType())) {
            wrapper.eq("type", userSearch.getType());
        }

        IPage<User> userPage = userMapper.selectPage(page, wrapper);

        System.out.println(userPage);
        Result<SearchUserVo> r = new Result<>();
        SearchUserVo vo = new SearchUserVo();
        vo.setPageNum(Integer.parseInt(userPage.getCurrent() + ""));
        vo.setPageSize(Integer.parseInt(userPage.getSize() + ""));
        vo.setUserList(userPage.getRecords());
        vo.setTotal(userPage.getTotal());
        return r.setCode(200).setData(vo).setMsg("请求成功");
    }

    /**
     * 检查邮箱是否存在
     *
     * @param email
     * @return
     */
    @Override
    public Result checkEmailExist(String email) {
        // 构造条件
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("email", email);
        List<User> userList = userMapper.selectList(queryWrapper);
        if (!ObjectUtils.isEmpty(userList) && userList.size() > 0) {
            // 说明用户名已存在
            log.warn("【用户模块】:邮箱:{}已存在,检验不通过", email);
            return Result.ok().setData(userList.size());
        }
        //  不存在
        log.info("【用户模块】:用户名:{}检验通过", email);
        return Result.ok().setData(0);
    }

    /**
     * 后台添加用户
     *
     * @param userdto
     * @return
     */
    @Override
    @MarkLog(operate = OperaTypeEnum.INSERT,tables = {TableEnum.SYS_USER},desc = "管理员添加用户")
    @Transactional
    public Result add(UserInsertDto userdto) {
        String salt = StringUtil.generatorUniqueSalt();
        String password = passwordEncryptor.encryptPassword(CommonContent.RESET_PASSWORD);
        User user = new User();
        user.setLoginName(userdto.getEmail());
        user.setPwd(password);
        user.setSalt(salt);
        user.setEmail(userdto.getEmail());
        user.setType(userdto.getType());
        user.setAvailable(userdto.getAvailable());
        user.setRegisterTime(new Date());
        int i = userMapper.insert(user);
        if (i != 1) {
            throw new RspException(ResponseStateConstant.OPERA_FAIL, "用户添加失败");
        }

        // 授衔
        UserRank rank = new UserRank();
        rank.setUserId(user.getUserId());
        rank.setRankId(2);
        if (userRankMapper.insert(rank) != 1){
            return Result.error("用户:" + user.getEmail() + "注册失败,请重新尝试");
        }

        Integer result = 0;
        // 给用户授权
        if (user.getType() == 2){
            // 授权管理员
            RoleUser roleUser = new RoleUser();
            roleUser.setUid(user.getUserId());
            roleUser.setRid(2);
            result = roleUserMapper.insert(roleUser);
            // 授衔
            UserRank userRank = new UserRank();
            userRank.setUserId(user.getUserId());
            userRank.setRankId(3);
            if (userRankMapper.insert(userRank) != 1){
                return Result.error("管理员:" + user.getEmail() + "注册失败,请重新尝试");
            }
        } else if (user.getType() == 3){
            // 授权用户
            RoleUser roleUser = new RoleUser();
            roleUser.setUid(user.getUserId());
            roleUser.setRid(3);
            result = roleUserMapper.insert(roleUser);
        } else {
            return Result.error("用户类型暂未授权");
        }
        if (result > 0){
            StringJoiner joiner = new StringJoiner("<br/>");
            joiner.add("<h4>用户您好，您的账户已经创建成功</h4>");
            joiner.add("<h4>用户名:" + userdto.getEmail() + "</h4>");
            joiner.add("<h4>密码:"+ CommonContent.RESET_PASSWORD +"</h4>");
            joiner.add("<h4>友情提醒:请及时修改个人信息,祝您愉快!</h4>");
            try {
                mailSendUtil.send("资源共享平台", new String[]{userdto.getEmail()},joiner.toString());
            } catch (MessagingException e) {
                e.printStackTrace();
                throw new RspException("用户添加失败");
            }
            return Result.ok("用户添加成功");
        } else {
            throw new RspException("用户添加失败");
        }
    }

    /**
     * 后台修改用户
     *
     * @param userdto
     * @return
     */
    @Override
    @MarkLog(operate = OperaTypeEnum.UPDATE,tables = {TableEnum.SYS_USER},desc = "管理员修改用户")
    public Result update(UserInsertDto userdto) {
        Integer available = userdto.getAvailable();
        if (available == 1 || available == 0){
            User user = new User();
            user.setUserId(userdto.getUserId());
            user.setAvailable(available);
            int i = userMapper.updateById(user);
            if (i != 1) {
                throw new RspException(ResponseStateConstant.OPERA_FAIL, "用户修改失败");
            }
            return Result.ok("用户修改成功");
        }
        return Result.error().setCode(400).setMsg("入参错误");
    }

    /**
     * 重置用户密码
     *
     * @param userId
     * @return
     */
    @Override
    @MarkLog(operate = OperaTypeEnum.UPDATE,tables = {TableEnum.SYS_USER},desc = "管理员重置用户密码")
    public Result resetPwd(Integer userId) {
        String password = passwordEncryptor.encryptPassword(CommonContent.RESET_PASSWORD);
        User user = new User();
        user.setUserId(userId);
        user.setPwd(password);

        int i = userMapper.updateById(user);
        if (i != 1) {
            throw new RspException(ResponseStateConstant.OPERA_FAIL, "密码重置失败");
        }
        return Result.ok("密码重置成功");
    }

    /**
     * 后台登陆成功处理
     *
     * @param loginUser
     * @param vo
     * @return
     */
    @Override
    public void loginSuccess(User loginUser,AuthResultVo vo) {
        JwtUser user = new JwtUser(loginUser.getUserId(),loginUser.getLoginName());
        // 生成token
        try {
            String token = JwtUtil.generateToken(user, scricet, expires);
            String key = UUID.randomUUID().toString().replace("-","");
            // 获得用户菜单
            Result<MenuVo> menuList = menuService.getMenuByUserId(loginUser.getUserId());
            // 修改登录时间
            userMapper.updateById(new User().setUserId(loginUser.getUserId()).setLastLoginTime(new Date()));
            // 存token
            cacheUtils.set(CachePrefixContent.TOKEN_PREFIX + key, token, expires);
            vo.setLoginUser(loginUser);
            vo.setToken(key);
            vo.setUserMenus(menuList.getData());
        } catch (Exception e) {
            e.printStackTrace();
            log.error("生成token失败,{}",e.getMessage());
            throw new RspException(RspEnum.AUTH_LOGIN_ERROR);
        }
    }

    /**
     * 用户名密码登录-
     *
     * @param user
     * @return
     */
    @Override
    public User usernameLogin(AdminLoginDto user) {
        if (!StringUtils.hasLength(user.getUsername())) {
            throw new RspException(ResponseStateConstant.PARAMETER_ERROR, "用户名不能为空");
        }
        if (!StringUtils.hasLength(user.getPassword())) {
            throw new RspException(ResponseStateConstant.PARAMETER_ERROR, "密码不能为空");
        }
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.eq("login_name", user.getUsername());
        User userObj = userMapper.selectOne(wrapper);
        if (userObj == null) {
            throw new RspException(ResponseStateConstant.OPERA_FAIL, "用户名或密码错误");
        }
        if (passwordEncryptor.checkPassword(user.getPassword(), userObj.getPwd())){
            if (userObj.getAvailable() != null && userObj.getAvailable() == 0){
                throw new RspException(ResponseStateConstant.OPERA_FAIL, "登陆失败,用户账号异常,暂停服务");
            }
            return userObj;
        }
        return null;
    }

    /**
     * 邮箱登录
     *
     * @param user
     * @return
     */
    @Override
    public User emailLogin(AdminLoginDto user) {
        if (!StringUtils.hasLength(user.getEmail())) {
            throw new RspException(ResponseStateConstant.PARAMETER_ERROR, "邮箱不能为空");
        }
        if (!StringUtils.hasLength(user.getCode())) {
            throw new RspException(ResponseStateConstant.PARAMETER_ERROR, "验证码不能为空");
        }
        // 查询邮箱是否存在且唯一
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.eq("email",user.getEmail());
        List<User> userList = userMapper.selectList(wrapper);
        if (!ObjectUtils.isEmpty(userList) && userList.size() == 1){
            String code = cacheUtils.get(CachePrefixContent.EMAIL_PREFIX + user.getEmail());
            if (StringUtils.isEmpty(code)){
                throw new RspException(201,"验证码已过期,请重新尝试");
            }

            if (user.getCode().equals(code)){
                User userObj = userList.get(0);
                if (userObj.getAvailable() != null && userObj.getAvailable() == 0){
                    throw new RspException(ResponseStateConstant.OPERA_FAIL, "登陆失败,您的账号异常,请联系管理员");
                }

                return userObj;
            }
        }
        return null;
    }

    /**
     * 获得我的详细信息
     * @return
     */
    @Override
    public void getMyInfo(Result<UserInfoVo> r) {
        UserInfoVo userInfoVo = new UserInfoVo();
        User user = AuthCacheService.getUser();
        if (user == null){
            r.setCode(201).setMsg("获取失败");
            log.error("用户已过期,{}",user);
            return;
        }
        BeanUtils.copyProperties(user,userInfoVo);
        // 获取自定义标签
        String label = user.getLabel();
        if (StringUtils.hasLength(label)){
            String[] labels = label.split(",");
            if (labels != null && labels.length > 0){
                userInfoVo.setUserLabel(Arrays.asList(labels));
            }
        }
        // 获取系统头衔
        List<Rank> rankList = rankService.getRankList(user.getUserId());
        if(!CollectionUtils.isEmpty(rankList)){
            List<RankVo> list = new ArrayList<>();
            rankList.stream().forEach(rank -> {
                RankVo vo = new RankVo();
                BeanUtils.copyProperties(rank, vo);
                list.add(vo);
            });
            userInfoVo.setUserRank(list);
        }

        userInfoVo.setSexName(SexEnum.getSex(user.getSex()));
        userInfoVo.setType(UserTypeEnum.getType(user.getType()));
        if (user.getOccupation() != null){
            Occupation occupation = occupationService.getById(user.getOccupation());
            userInfoVo.setOccupationName(occupation != null ? occupation.getOccuName() : "");
        }

        r.setCode(200).setData(userInfoVo);
    }

    /**
     * 用户更新头像
     * @param file
     * @param r
     * @throws Exception
     */
    @Override
    public void updateAvator(MultipartFile file, Result r) throws Exception {
        if (file.isEmpty()){
            r.setCode(ResponseStateConstant.PARAMETER_ERROR).setMsg("文件不能为空");
            log.error("【用户模块】:上传的文件不能为空");
            return;
        }
        if (file.getSize() > CommonContent.FILE_MAX_SIZE){
            r.setCode(ResponseStateConstant.OPERA_FAIL).setMsg("文件大小超过限制");
            log.error("【用户模块】:文件大小超过限制");
            return;
        }
        String url = fileUploadUtil.uploadAndUrl(StringUtil.generatorFileName() + CommonContent.PREFIX_IMG, file.getBytes());
        if (StringUtils.hasLength(url)){
            User user = AuthCacheService.getUser();
            User updateUser = new User().setUserId(user.getUserId()).setAvator(url);
            int result = userMapper.updateById(updateUser);
            if (result == 1){
                r.setCode(200).setData(url).setMsg("文件上传成功");
            } else {
                throw new RspException(201,"文件上传失败");
            }
        }

    }

    /**
     * 修改用户信息
     * @param updateUserDto
     * @param r
     */
    @Override
    public void updateInfo(UpdateUserDto updateUserDto, Result r) {
        if (updateUserDto.getUserId() == null){
            r.setCode(ResponseStateConstant.OPERA_FAIL).setMsg("用户id不能为null");
            return;
        }
        User user = AuthCacheService.getUser();
        if (user == null){
            r.setCode(ResponseStateConstant.NO_LOGIN).setMsg("用户登录已过期");
            return;
        }
        if (!updateUserDto.getUserId().equals(user.getUserId())){
            r.setCode(ResponseStateConstant.NO_PROMISSION).setMsg("非法操作");
            return;
        }

        User updateUser = new User();
        BeanUtils.copyProperties(updateUserDto,updateUser);
        List<String> strings = updateUserDto.getUserLabel();
        if (!CollectionUtils.isEmpty(strings)){
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < strings.size(); i++) {
                if (i != strings.size() -1){
                    sb.append(strings.get(i));
                    sb.append(",");
                }else {
                    sb.append(strings.get(i));
                }
            }
            updateUser.setLabel(sb.toString());
        } else {
            updateUser.setLabel("");
        }

        int result = userMapper.updateById(updateUser);
        if (result == 1){
            r.setCode(ResponseStateConstant.OPERA_SUCCESS).setMsg("用户信息已更新");
        }else {
            r.setCode(ResponseStateConstant.OPERA_FAIL).setMsg("用户信息更新失败");
        }
    }

    /**
     * 删除用户信息
     * @param userId
     * @param r
     */
    @Override
    @Transactional
    @MarkLog(operate = OperaTypeEnum.DELETE, tables = {TableEnum.SYS_USER,TableEnum.SYS_ROLE_USER}, desc = "管理员删除用户信息及授权信息")
    public void deleteUser(Integer userId, Result r) {
        int result = userMapper.deleteById(userId);
        if (result != 1){
            throw new RspException("删除失败");
        }
        QueryWrapper<RoleUser> wrapper = new QueryWrapper<>();
        wrapper.eq("uid",userId);
        // 删除用户授权信息
        roleUserMapper.delete(wrapper);
        r.setCode(200).setMsg("用户删除成功");
    }

    /**
     * 给用户授权
     * @param userAuthDto
     */
    @Override
    @Transactional
    @MarkLog(operate = OperaTypeEnum.UPDATE,tables = TableEnum.SYS_ROLE_USER, desc = "给用户授权")
    public void saveRoleToUser(UserAuthDto userAuthDto, Result r) {
        Integer userId = userAuthDto.getUserId();
        List<Integer> ids = userAuthDto.getIds();
        // 删除原有权限
        QueryWrapper<RoleUser> wrapper = new QueryWrapper<>();
        wrapper.eq("uid",userId);
        List<RoleUser> roleUsers = roleUserMapper.selectList(wrapper);
        if (CollectionUtils.isEmpty(roleUsers)){
            // 重新授权
            if (CollectionUtils.isEmpty(ids)){
                r.setCode(200).setMsg("权限回收成功");
            } else {
                int result = roleUserMapper.insertBatch(userId, ids);
                if (result > 0){
                    if (ids.contains(2)){
                        // 修改用户类型
                        User user = new User();
                        user.setUserId(userAuthDto.getUserId());
                        user.setType(2);
                        int i = userMapper.updateById(user);
                        if (i == 1){
                            r.setCode(200).setMsg("给用户授权成功");
                            return;
                        }
                        throw new RspException("给用户授权失败");
                    }else {
                        r.setCode(200).setMsg("给用户授权成功");
                    }
                } else{
                    throw new RspException("给用户授权失败");
                }
            }
        } else {
            int delete = roleUserMapper.delete(wrapper);
            if (delete > 0){
                // 修改用户类型
                User userD = new User();
                userD.setUserId(userAuthDto.getUserId());
                userD.setType(3);
                int res = userMapper.updateById(userD);
                if (res != 1){
                    throw new RspException("给用户授权失败");
                }
                // 重新授权
                if (CollectionUtils.isEmpty(ids)){
                    r.setCode(200).setMsg("权限回收成功");
                } else {
                    int result = roleUserMapper.insertBatch(userId, ids);
                    if (result > 0){
                        if (ids.contains(2)){
                            // 修改用户类型
                            User user = new User();
                            user.setUserId(userAuthDto.getUserId());
                            user.setType(2);
                            int i = userMapper.updateById(user);
                            if (i == 1){
                                r.setCode(200).setMsg("给用户授权成功");
                                return;
                            }
                            throw new RspException("给用户授权失败");
                        } else {
                            r.setCode(200).setMsg("给用户授权成功");
                        }
                    } else{
                        throw new RspException("给用户授权失败");
                    }
                }
            }else {
                throw new RspException("给用户授权失败");
            }
        }
    }

    /**
     * 检查旧密码是否正确
     * @param dto
     * @param r
     */
    @Override
    public void checkOldPassword(CheckPwdDto dto, Result r) {
        User user = userMapper.selectById(dto.getUserId());
        if (ObjectUtils.isEmpty(user)){
            r.setCode(201).setMsg("用户不存在");
            return;
        }
        String oldPwd = dto.getPwd();
        if (passwordEncryptor.checkPassword(oldPwd, user.getPwd())){
            r.setCode(200).setMsg("验证通过");
            return;
        }
        r.setCode(201).setMsg("验证不通过");
    }

    /**
     * 修改密码
     * @param dto
     * @param r
     */
    @Override
    @MarkLog(operate = OperaTypeEnum.UPDATE, tables = TableEnum.SYS_USER, desc = "修改密码")
    public void updatePassword(UpdatePwdDto dto, Result r) {
        User user = userMapper.selectById(dto.getUserId());
        if (ObjectUtils.isEmpty(user)){
            r.setCode(201).setMsg("用户不存在");
            return;
        }
        String oldPwd = dto.getOldPwd();
        if (passwordEncryptor.checkPassword(oldPwd, user.getPwd())){
            User newUser = new User();
            String password = passwordEncryptor.encryptPassword(dto.getPwd());
            newUser.setUserId(dto.getUserId());
            newUser.setPwd(password);
            int result = userMapper.updateById(newUser);
            if (result == 1){
                r.setCode(200).setMsg("用户:"+ user.getLoginName() + "密码修改成功");
                return;
            }
        }
        r.setCode(201).setMsg("用户:"+ user.getLoginName() + "密码修改失败");
    }

    /**
     * 给用户授衔
     * @param dto
     * @param r
     */
    @Override
    @Transactional
    public void saveRankToUser(UserRankDto dto, Result r) {
        User user = AuthCacheService.getUser();
        Integer userId = dto.getUserId();
        List<Integer> ids = dto.getIds();
        QueryWrapper<UserRank> wrapper = new QueryWrapper<>();
        wrapper.eq("user_id",userId);
        List<UserRank> userRanks = userRankMapper.selectList(wrapper);
        if (!CollectionUtils.isEmpty(userRanks)){
            int delete = userRankMapper.delete(wrapper);
            if (delete == 0){
                throw new RspException("授权失败");
            }
        }
        // 集合为空，不授衔
        if (CollectionUtils.isEmpty(ids)){
            r.setCode(200).setMsg("操作成功");
            return;
        }
        // 不是超管
        if (user.getType() != 1){
            if (ids.size() >= 5){
                throw new RspException(201, "头衔授予不能超过5个");
            }
        }
        // 直接授衔
        Integer result = userRankMapper.insertBatchs(userId, ids);
        if (result == 0){
            throw new RspException("授衔失败");
        }
        r.setCode(200).setMsg("授衔成功");
    }

    /**
     * 获得用户已有头衔id
     * @param userId
     * @param r
     */
    @Override
    public void getUserHasRankId(Integer userId, Result r) {
        List<UserRank> ranks = userRankMapper.selectList(new QueryWrapper<UserRank>().eq("user_id", userId));
        if (CollectionUtils.isEmpty(ranks)){
            r.setCode(200).setData(new ArrayList<>());
            return;
        }
        r.setCode(200).setData(ranks.stream().map(UserRank::getRankId).collect(Collectors.toList()));
    }

    @Override
    public void getUserInfo(Integer userId, Result<UserInfoVo> r) {
        UserInfoVo userInfoVo = new UserInfoVo();
        User user = userMapper.selectById(userId);
        if (user == null){
            r.setCode(201).setMsg("用户不存在");
            return;
        }
        BeanUtils.copyProperties(user,userInfoVo);
        // 获取自定义标签
        String label = user.getLabel();
        if (StringUtils.hasLength(label)){
            String[] labels = label.split(",");
            if (labels != null && labels.length > 0){
                userInfoVo.setUserLabel(Arrays.asList(labels));
            }
        }
        // 获取系统头衔
        List<Rank> rankList = rankService.getRankList(user.getUserId());
        if(!CollectionUtils.isEmpty(rankList)){
            List<RankVo> list = new ArrayList<>();
            rankList.stream().forEach(rank -> {
                RankVo vo = new RankVo();
                BeanUtils.copyProperties(rank, vo);
                list.add(vo);
            });
            userInfoVo.setUserRank(list);
        }

        userInfoVo.setSexName(SexEnum.getSex(user.getSex()));
        userInfoVo.setType(UserTypeEnum.getType(user.getType()));
        if (user.getOccupation() != null){
            Occupation occupation = occupationService.getById(user.getOccupation());
            userInfoVo.setOccupationName(occupation != null ? occupation.getOccuName() : "");
        }

        r.setCode(200).setData(userInfoVo);
    }

    @Override
    public void logOut(String token, Result r) {
        if (StringUtils.hasLength(token)) {
            if (cacheUtils.removeKey(CachePrefixContent.TOKEN_PREFIX + token)){
                r.setCode(200).setMsg("操作成功");
                return;
            }
            r.setCode(201);
        }
    }
}
